#include "PEIncludes.h"

#include "PEAliceSoftLoader.h"

#include "PEImage.h"
#include "PEAliceSoftArchiveRed.h"
#include "PEAliceSoftArchiveAfa.h"
#include "PEAliceSoftArchiveAld.h"
#include "PEAliceSoftZipped.h"
#include "PEAliceSoftImageQnt.h"
#include "PEAliceSoftImagePms.h"
#include "PEAliceSoftImageAjp.h"
#include "PEAliceSoftImageJpg.h"
#include "PEAliceSoftImageVsp.h"
#include "PEAliceSoftModel.h"
#include "PEAliceSoftAnimation.h"

namespace pe
{

	PE_EXPORT int CreateLoader(PELoader** a_Target)
	{
		*a_Target = new AliceSoftLoader();
		return PE_OK;
	}

	AliceSoftLoader::AliceSoftLoader() : PELoader()
	{

	}

	AliceSoftLoader::~AliceSoftLoader()
	{

	}

	/*int AliceSoftLoader::CheckArchive(char** a_Dst, PEStream* a_Stream)
	{
		size_t offset;
		PEStreamGetCurrentPos(a_Stream, &offset);

		// ================================
		// Archive ALD
		// ================================

		AliceArchiveAldHeader arch_ald;
		if (AliceArchiveAldReadHeader(&arch_ald, a_Stream) == PE_OK)
		{
			PE_STRCLRCPY(*a_Dst, "(AliceSoft)[Archive]Ald");
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Archive RED
		// ================================

		AliceArchiveRedHeader arch_red;
		if (AliceArchiveRedReadHeader(&arch_red, a_Stream) == PE_OK)
		{
			PE_STRCLRCPY(*a_Dst, "(AliceSoft)[Archive]Red");
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Archive AFA
		// ================================

		AliceArchiveAfaHeader arch_afa;
		if (AliceArchiveAfaReadHeader(&arch_afa, a_Stream) == PE_OK)
		{
			PE_STRCLRCPY(*a_Dst, "(AliceSoft)[Archive]Afa");
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		return -1;
	}

	int AliceSoftLoader::CheckImage(char** a_Dst, PEStream* a_Stream)
	{
		size_t offset;
		PEStreamGetCurrentPos(a_Stream, &offset);

		// ================================
		// Image QNT
		// ================================

		AliceImageQntHeader image_qnt;
		if (AliceImageQntReadHeader(&image_qnt, a_Stream) == PE_OK)
		{
			PE_STRCLRCPY(*a_Dst, "(AliceSoft)[Image]Qnt");
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Image PMS
		// ================================

		AliceImagePmsHeader image_pms;
		if (AliceImagePmsReadHeader(&image_pms, a_Stream) == PE_OK)
		{
			PE_STRCLRCPY(*a_Dst, "(AliceSoft)[Image]Pms");
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Image AJP
		// ================================

		AliceImageAjpHeader image_ajp;
		if (AliceImageAjpReadHeader(&image_ajp, a_Stream) == PE_OK)
		{
			PE_STRCLRCPY(*a_Dst, "(AliceSoft)[Image]Ajp");
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		return -1;
	}*/

	PEImage* AliceSoftLoader::CheckImage(PEStream* a_Stream)
	{
		size_t offset;
		PEStreamGetCurrentPos(a_Stream, &offset);

		// ================================
		// Image QNT
		// ================================

		ImageAliceSoftQnt* image_qnt = new ImageAliceSoftQnt;
		if (image_qnt->LoadHeader(a_Stream) == PE_OK) { return image_qnt; }
		delete image_qnt;

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Image PMS
		// ================================

		ImageAliceSoftPms* image_pms = new ImageAliceSoftPms;
		if (image_pms->LoadHeader(a_Stream) == PE_OK) { return image_pms; }
		delete image_pms;

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// Image AJP
		// ================================

		ImageAliceSoftAjp* image_ajp = new ImageAliceSoftAjp;
		if (image_ajp->LoadHeader(a_Stream) == PE_OK) { return image_ajp; }
		delete image_ajp;

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		return NULL;
	}

	/*int AliceSoftLoader::CheckModel(char** a_Dst, PEStream* a_Stream)
	{
		size_t offset;
		PEStreamGetCurrentPos(a_Stream, &offset);

		// ================================
		// Model
		// ================================

		AliceModelHeader model;
		if (AliceModelReadHeader(&model, a_Stream) == PE_OK)
		{
			PE_STRCLRCPY(*a_Dst, "(AliceSoft)[Model]");
			PEStreamSeek(a_Stream, offset, SEEK_SET);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		return -1;
	}*/

	int AliceSoftLoader::LoadRawArchive(PEArchiveRaw& a_Dst, PEStream* a_Stream)
	{
		size_t offset;
		PEStreamGetCurrentPos(a_Stream, &offset);

		AliceArchiveRedHeader red_header;
		if (AliceArchiveRedReadHeader(&red_header, a_Stream) == PE_OK)
		{
			AliceArchiveRed red_arch;
			AliceArchiveRedReadData(&red_arch, &red_header, a_Stream);

			AliceArchiveRedToRaw(&a_Dst, &red_arch);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		AliceArchiveAfaHeader afa_header;
		if (AliceArchiveAfaReadHeader(&afa_header, a_Stream) == PE_OK)
		{
			AliceArchiveAfa afa_arch;
			AliceArchiveAfaReadData(&afa_arch, &afa_header, a_Stream);

			AliceArchiveAfaToRaw(&a_Dst, &afa_arch);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		AliceArchiveAldHeader ald_header;
		if (AliceArchiveAldReadHeader(&ald_header, a_Stream) == PE_OK)
		{
			AliceArchiveAld ald_arch;
			AliceArchiveAldReadData(&ald_arch, &ald_header, a_Stream);

			AliceArchiveAldToRaw(&a_Dst, &ald_arch);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		return -1;
	}

	int AliceSoftLoader::LoadRawImage(PEImageRaw& a_Dst, PEStream* a_Stream)
	{
		size_t offset;
		PEStreamGetCurrentPos(a_Stream, &offset);

		// ================================
		// QNT
		// ================================

		AliceImageQntHeader qnt_header;
		if (AliceImageQntReadHeader(&qnt_header, a_Stream) == PE_OK)
		{
			AliceImageQnt qnt_data;
			AliceImageQntReadData(&qnt_data, &qnt_header, a_Stream);

			AliceImageQntToRaw(&a_Dst, &qnt_data);

			AliceImageQntDeleteData(&qnt_data);
			AliceImageQntDeleteHeader(&qnt_header);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// PMS
		// ================================

		AliceImagePmsHeader pms_header;
		if (AliceImagePmsReadHeader(&pms_header, a_Stream) == PE_OK)
		{
			AliceImagePms pms_data;
			AliceImagePmsReadData(&pms_data, &pms_header, a_Stream);

			AliceImagePmsToRaw(&a_Dst, &pms_data);

			AliceImagePmsDeleteData(&pms_data);
			AliceImagePmsDeleteHeader(&pms_header);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		// ================================
		// AJP
		// ================================

		AliceImageAjpHeader ajp_header;
		if (AliceImageAjpReadHeader(&ajp_header, a_Stream) == PE_OK)
		{
			AliceImageAjp ajp_data;
			AliceImageAjpReadData(&ajp_data, &ajp_header, a_Stream);

			AliceImageAjpToRaw(&a_Dst, &ajp_data);

			AliceImageAjpDeleteData(&ajp_data);
			AliceImageAjpDeleteHeader(&ajp_header);

			return PE_OK;
		}

		PEStreamSeek(a_Stream, offset, SEEK_SET);

		return -1;
	}

	int AliceSoftLoader::LoadRawModel(PEModelRaw& a_Dst, PEStream* a_Stream)
	{
		return -1;
	}
}